package com.spring.controller.web;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.ListUtils;
import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import com.spring.domain.User;
import com.spring.mail.MailService;
import com.spring.service.user.IUser;
import com.utils.Validation;

public class UserController extends MultiActionController {
	private static final Logger logger = Logger.getLogger(UserController.class);
    private IUser userService;
    private final String ACTION_DELETE 			=	"delete";
    private final String ACTION_RELATE_CONTENT 	=	"relate";
    private final String ACTION_DISABLE		 	=	"disable";
    private MailService mailService;
    
    public ModelAndView userList(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String now = (new java.util.Date()).toString();
        logger.info("Creating model");
        Map<String,Object> model = new HashMap<String, Object>();        
        model.put("now", now);
        model.put("users", this.userService.getUsers());
    		
        logger.info("Returning user/userList view");

        return new ModelAndView("user/userList", "model", model);
    }
    
    public ModelAndView manageUsers(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    	
    	List<String> 	messages 		= new ArrayList<String>();
    	List<HashMap> 	errorMessages 	= new ArrayList<HashMap>();
    	
    	Map<String,Object> model = new HashMap<String, Object>(); 
        
    	List<String> idSelected = Arrays.asList (ServletRequestUtils.getStringParameters(request, "userId") );
        if(idSelected.isEmpty()){
        	final String field = getApplicationContext().getMessage("text.password", 
					new Object[] { "password" }, Locale.getDefault());
        	
        	errorMessages.add(new HashMap<String,String>(){{
    			put("key","manageUser.nothingSelected");
    			put("param1","");
    		}});
        }
        
        String action = ServletRequestUtils.getStringParameter	(request, "action"		,"0");
        logger.info("action recuperata:"+action);
        
        if(ACTION_DELETE.equalsIgnoreCase(action)){
        	List<User> users = getUserList(request);
        	if(users.isEmpty()){
			}else{
				this.userService.delete(users);
        		messages.add("manageUser.okDelete");
			}
        }
        
               
        model.put("users", this.userService.getUsers());
        model.put("messages", messages);
        model.put("errors", errorMessages);
        
        logger.info("Returning user/userList view");
        return new ModelAndView("user/userList", "model", model);
    }

	private List<User> getUserList(HttpServletRequest request) {
		List<String> userIds = request.getParameterValues("userId") == null ? ListUtils.EMPTY_LIST : Arrays.asList(request.getParameterValues("userId")) ;
		List<User> users = new ArrayList<User>();
		for (Iterator<String> iterator = userIds.iterator(); iterator.hasNext();) {
			final String string = iterator.next();
			users.add(new User(){{
				setId(Integer.valueOf(string).intValue());
				}}
			);
		}
		return users;
	}
    
    
   
    
    public ModelAndView newUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        List<HashMap> errorMessages = new ArrayList<HashMap>();
        List<String> messages = new ArrayList<String>();
        Map<String,Object> model = new HashMap<String, Object>();   
        String view = new String("user/newUser");
        
        User userDataForm = getNewUserForm(request);
        if (validateNewUserDataForm(userDataForm, errorMessages)){
        	logger.info("Inserting user " + userDataForm.getMail() + " and pwd "+ userDataForm.getPwd());
        	
        	String activationCode = String.valueOf(UUID.randomUUID()).substring(0,6);
        	
        	//insert User
        	logger.info("INSERIMENTO UTENTE");
        	userDataForm.setActivationCode(activationCode);
        	
        	int idUserInserted = userService.insert(userDataForm);
        	
        	User insertedUser = (User)this.userService.getUserById(idUserInserted);
        	insertedUser.setActivationCode(activationCode);
        	
        	String activateUser = ServletRequestUtils.getStringParameter(request, "activateUser",null);        	
        	if( activateUser == null ){
	        	logger.info("START > INVIO MAIL DATI ATTIVAZIONE ACCOUNT");
	        	mailService.sendRegistrationEmail(insertedUser);
	        	logger.info("END   > INVIO MAIL DATI ATTIVAZIONE ACCOUNT");
        	}else{
        		logger.info("SCELTA ATTIVAZIONE UTENTE AUTOMATICA  ");
            	logger.info("UPDATE UTENTE CON CODICE ATTIVAZIONE");
            	userService.update(insertedUser);
        	}
        	messages.add("ok.insertedUser");
        	model.put("messages", messages);
        	
        }else{
        	model.put("errors", errorMessages);
        	model.put("user", userDataForm);
        }
        
        
        logger.info("Returning view:["+view+"]");
        return new ModelAndView(view, "model", model);
    }
    
    
    public ModelAndView activateUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        List<HashMap> errorMessages = new ArrayList<HashMap>();
        List<String> messages = new ArrayList<String>();
        Map<String,Object> model = new HashMap<String, Object>();   
        String view = new String("user/activate");
        
        User activateUserForm = getActivateUserForm(request);
        if (validateActivateUserForm(activateUserForm, errorMessages)){
        	
        	logger.info("activate user " + activateUserForm.getMail() + " and activationCode "+ activateUserForm.getActivationCode());
        	
        	List<User> users = this.userService.getUserByMail(activateUserForm);
        	
        	if(users!=null && !users.isEmpty()){
        		
        		for (Iterator<User> iter = users.iterator(); iter.hasNext();) {
					User userFound = iter.next();
					
					if(userFound.getActivationCode()==null){
						logger.info("NULL CODE RETRIEVED FROM DB ACTIVATION CODE");
					}else if(!userFound.getActivationCode().equalsIgnoreCase(activateUserForm.getActivationCode())){
	            		
						logger.info("WRONG ACTIVATION CODE");
	            		errorMessages.add(new HashMap<String, String>(){{
	            			put("key","validation.activateUser.wrongCode");
	            			put("param1","");
	            		}});
	            	}else if(userFound.getActivationCode().equalsIgnoreCase(activateUserForm.getActivationCode())){
	            		logger.info("FOUND USER TO ACTIVATE");
	            		//update user with startDate and no activaton code
	            		userFound.setStartDate(new Date());
	            		userFound.setActivationCode("");
	            		userService.update(userFound);
	            		messages.add("ok.activateUser");
	            		logger.info("USER ACTIVATED");
	            		activateUserForm=null;
	            	}
				}
        		
        	}else{
        		logger.info("NO USER FOUND ON DB");
        		errorMessages.add(new HashMap<String, String>(){{
        			put("key","validation.activateUser.wrongMail");
        			put("param1","");
        		}});
        	}
        }
        
        model.put("user", activateUserForm);
        model.put("errors", errorMessages);
        model.put("messages", messages);
        
        logger.info("Returning view:["+view+"]");
        return new ModelAndView(view, "model", model);
    }
    
    /**
     * 	VALIDAZIONE FORM INSERIMENTO
     * */
    private boolean validateNewUserDataForm(User userForm, List<HashMap> error) {
    
    	User user = (User) userForm;
    	
    	if( !Validation.emailValidator(user.getMail()) ){
    		error.add(new HashMap<String,String>(){{
    			put("key","validation.mail");
    		}});
    	}
    	
    	if( !StringUtils.hasText( user.getPwd() ) ){
    		
    		final String field = getApplicationContext().getMessage("text.password", 
					new Object[] { "password" }, Locale.getDefault());
					
    		error.add(new HashMap<String,String>(){{
    			put("key","validation.notEmptyAllowed");
    			put("param1",field);
    		}});
    	}
    	
    	if(error.isEmpty()) return true;
    	
    	return false;
    	
	}
    
    /**
     * 	VALIDAZIONE FORM ATTIVAZIONE UTENTE
     * */ 
    private boolean validateActivateUserForm(User userForm, List<HashMap> error) {
    
    	User user = (User) userForm;
    	
    	if( !Validation.emailValidator(user.getMail()) ){
    		final String field = getApplicationContext().getMessage("text.mail", null, Locale.getDefault());
					
    		error.add(new HashMap<String,String>(){{
    			put("key","validation.malformedEntry");
    			put("param1",field);
    		}});
    	}
    	
    	if( !StringUtils.hasText( user.getActivationCode() ) ){
    		
    		final String field = getApplicationContext().getMessage("text.activationCode", null, Locale.getDefault());
					
    		error.add(new HashMap<String,String>(){{
    			put("key","validation.notEmptyAllowed");
    			put("param1",field);
    		}});
    	}
    	
    	if(error.isEmpty()) return true;
    	
    	return false;
    	
	}
    
    /**
     * 	RECUPERO OGGETTO USER DA REQUEST PER ATTIVAZIONE FORM
     * */
    private User getActivateUserForm(HttpServletRequest req){
    	final String   mail = ServletRequestUtils.getStringParameter	(req, "mail"		,"");
    	final String   activationCode = ServletRequestUtils.getStringParameter	(req, "activationCode"		,"");
    	
    	return new User(){{
    		setMail(mail);
    		setActivationCode(activationCode);
    	}};
    	
    }

    
    /**
     * 	RECUPERO OGGETTO USER DA REQUEST PER INSERIMENTO UTENTE
     * */
	private User getNewUserForm(HttpServletRequest req){
    	final String   	id			= ServletRequestUtils.getStringParameter(req, "id"			,"0");
    	final String 	mail		= ServletRequestUtils.getStringParameter(req, "mail"		,"");
    	final String 	pwd			= ServletRequestUtils.getStringParameter(req, "pwd"			,"");
    	final String	newsLetter 	= ServletRequestUtils.getStringParameter(req, "newsLetter"	,null);
    	final String	admin   	= ServletRequestUtils.getStringParameter(req, "admin"		,null);
    	final int inewsLetter = StringUtils.hasText(newsLetter) ? 1 : 0;
    	final int iadmin = StringUtils.hasText(admin) ? 1 : 0;
    	
    	return new User(){{
    		setId(Integer.valueOf(id));
    		setMail(mail);
    		setPwd(pwd);
    		setNewsLetter(inewsLetter);
    		setAdmin(iadmin);
    	}};
    }
    
	 /**
     * 	REDIREZIONI A JSP
     * */
    public ModelAndView index(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    	logger.info("Returning user/index view");
        return new ModelAndView("user/index");
    }
    
    public ModelAndView newUserPage(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        logger.info("Returning user/newUser view");
        return new ModelAndView("user/newUser");
    }
    
    
    public ModelAndView activateUserPage(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        logger.info("Returning user/activate view");
        return new ModelAndView("user/activate");
    }
    
    /**
     * SETTER E GETTER
     * */
    
	public IUser getUserService() {
		return userService;
	}

	public void setUserService(IUser userService) {
		this.userService = userService;
	}

	public MailService getMailService() {
		return mailService;
	}

	public void setMailService(MailService mailService) {
		this.mailService = mailService;
	}

}
